import { NgFor, NgIf } from '@angular/common';
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { NzTableModule, NzTrDirective } from 'ng-zorro-antd/table';
import { NzDividerModule } from "ng-zorro-antd/divider";
import { NzFormModule } from "ng-zorro-antd/form";
import { NzInputModule } from "ng-zorro-antd/input";
import { NzModalModule } from 'ng-zorro-antd/modal';
import { NzSelectModule } from "ng-zorro-antd/select";
import { NzButtonModule, NzButtonComponent } from 'ng-zorro-antd/button';
import type { Column, ModelObject } from '../../type';
import { FormsModule } from '@angular/forms';
import { NzMenuModule } from 'ng-zorro-antd/menu';
import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
import { FieldSelectorComponent } from '../field-selector/field-selector.component';
import { NzEmptyModule, NzEmptyComponent } from "ng-zorro-antd/empty";

@Component({
  selector: 'app-custom-base',
  standalone: true,
  imports: [
    NzTableModule, NzTrDirective, NgFor, NzDividerModule, NzFormModule, NzButtonComponent,
    NzInputModule, NzModalModule, NgIf, NzButtonModule, FormsModule, NzMenuModule, NzDropDownModule,
    NzModalModule, FieldSelectorComponent, NzInputModule, NzSelectModule, NzEmptyModule, NzEmptyComponent,
  ],
  templateUrl: './custom-base.component.html',
  styleUrl: './custom-base.component.less'
})
export abstract class CustomBaseComponent<T extends ModelObject> implements OnInit {
  isFieldsDialogVisible: boolean = false;
  dataItems: T[] = [];
  // expands: { [itemId: string]: boolean } = {};
  searchText = '';
  isSearching = false;
  tableHeight = window.innerHeight - 180;
  searchFields: (keyof T)[] = this.loadSearchFields();

  protected error: string | null = null;;

  // historyDataItems: { [uid: string]: T[] } = {};

  @ViewChild('dialog') dialog!: FieldSelectorComponent<T>;

  columns: Column<T>[] = this.getColumns();


  constructor(private elementRef: ElementRef) {
  }
  ngOnInit(): void {
    this.getLatestDataItems().then(r => {
      this.dataItems = r;
    })
  }

  abstract getColumns(): Column<T>[];
  abstract getDefaultSearchFields(): (keyof T)[];
  abstract getLatestDataItems(): Promise<T[]>;
  abstract searchDataItems(searchText: string, searchFields: (keyof T)[]): Promise<T[]>;
  abstract getHistoryDataItems(dataItem: T): Promise<T[]>;
  abstract getTreeField(): keyof T;
  abstract getExportUrl(): string;

  private get storageName(): string {
    return (this.elementRef.nativeElement as HTMLElement).tagName;
  }

  getTreeFieldString(): string {
    return this.getTreeField() as string;
  }

  export() {
    window.open(this.getExportUrl(), "new");
  }

  async search() {
    this.isSearching = true;
    let searchText = this.searchText.trim();
    this.searchDataItems(searchText, this.searchFields)
      .then(r => {
        this.dataItems = r;
      })
      .finally(() => {
        this.isSearching = false;
      })
  }

  async onSearchInputKeydown(event: KeyboardEvent) {
    if (event.key == 'Enter') {
      this.search();
    }
  }

  async loadHistor(item: T, isExpand: boolean) {
    item.expands = isExpand;
    if (item.children) {
      return;
    }

    let productSummaries = await this.getHistoryDataItems(item);//await this.tcService.getHistoryProductSummary([item.item_id]);
    item.children = productSummaries;
    this.dataItems = JSON.parse(JSON.stringify(this.dataItems));
  }

  hideFieldsDialog() {
    this.isFieldsDialogVisible = false;
  }

  showFieldsDialog() {
    this.dialog.show(this.searchFields, (selectedFields) => {

      while (this.searchFields.length > 0)
        this.searchFields.pop();

      this.searchFields.push(...selectedFields);
      this.saveSearchFields(this.searchFields);
    });
  }

  onFieldChanged(event: Event, field: keyof T) {
    let input = event.target as HTMLInputElement;
    if (input.checked) {
      this.searchFields.push(field);
    }
    else {
      if (this.searchFields.length == 1) {
        //TODO: 至少保留一项 显示错误信息
        return;
      }
      this.searchFields = this.searchFields.filter(O => O != field);
    }
  }

  getSearchInputPlaceHolderText() {
    let names = this.columns.filter(o => this.searchFields.indexOf(o.field) >= 0).map(o => o.title).join('、');
    return `请输入${names}，按回车进行搜索`;
  }

  loadSearchFields() {
    let text = localStorage.getItem(this.storageName);
    let searchFields: (keyof T)[];
    if (!text) {
      searchFields = this.getDefaultSearchFields();// ['big_classname', 'project_name', 'usage', 'projectcode_id_last', 'project_size_yc'];
      text = JSON.stringify(searchFields);
      localStorage.setItem(this.storageName, text);
    }
    else {
      searchFields = JSON.parse(text);
    }

    return searchFields;
  }

  saveSearchFields(fields: (keyof T)[]) {
    let text = JSON.stringify(fields);
    localStorage.setItem(this.storageName, text);
  }

  case(obj: ModelObject): T {
    return obj as T;
  }

}
